﻿using System;
using System.IO;
using System.Xml;
using System.Collections.Generic;
using System.Xml.Serialization;

namespace ConnectServer
{
    /// <summary>
    /// ConnectServer's config singleton.
    /// </summary>
    [Serializable]
    public class Config
    {
        #region Config serializable classes
        [XmlRoot("config")]
        public class ConnectServer
        {
            [XmlElement("verbose")]
            public bool Verbose { get; set; }

            [XmlElement("bind_ip")]
            public string BindIP { get; set; }

            [XmlElement("max_connections")]
            public int MaxConnections { get; set; }

            [XmlElement("port")]
            public int Port { get; set; }

            [XmlElement("group")]
            public List<ServerGroup> ServerGroups { get; set; }
        }

        public class ServerGroup
        {
            [XmlAttribute("name")]
            public string Name { get; set; }

            [XmlElement("server")]
            public List<Server> Servers { get; set; }
        }

        public class Server
        {
            [XmlAttribute("ip")]
            public string IP { get; set; }
            [XmlAttribute("port")]
            public int Port { get; set; }
            [XmlAttribute("maxplayers")]
            public int MaxPlayers { get; set; }
        }
        #endregion

        #region Constants
        const string CONFIG_FILE_NAME = "connectserver.config";
        #endregion

        #region Singleton
        private static volatile Config m_instance;
        private static object m_mutex = new Object();

        public static Config Instance
        {
            get
            {
                if (m_instance == null)
                {
                    lock (m_mutex)
                    {
                        if (m_instance == null)
                            m_instance = new Config();
                    }
                }

                return m_instance;
            }
        }
        #endregion

        #region Ctor
        private Config()
        {
            Utilities.Logger.Instance.Log("Processing config...");
            System.Xml.Serialization.XmlSerializer xs
               = new System.Xml.Serialization.XmlSerializer(
                  typeof(ConnectServer));
            StreamReader reader = File.OpenText(CONFIG_FILE_NAME);
            ConnectServer config = (ConnectServer)xs.Deserialize(reader);
            this.config = config;
            reader.Close();
            Utilities.Logger.Instance.Log("Config processed successfully.");
        }
        #endregion

        #region Methods

        /// <summary>
        ///  Saves the configuration to a file
        /// </summary>
        /// <param name="file">The file to save to.</param>
        public void Save(string file=CONFIG_FILE_NAME)
        {
            System.Xml.Serialization.XmlSerializer xs
               = new System.Xml.Serialization.XmlSerializer(this.GetType());
            StreamWriter writer = File.CreateText(file);
            xs.Serialize(writer, this);
            writer.Flush();
            writer.Close();
        }
        #endregion

        #region Properties

        public List<ServerGroup> Groups
        {
            get { return this.config.ServerGroups; }
        }

        public string BindIP { get { return this.config.BindIP; } }

        public int MaxConnections { get { return this.config.MaxConnections; } }

        public int Port { get { return this.config.Port; } }

        public bool Verbose { get { return this.config.Verbose; } }
        #endregion

        #region Fields
        private ConnectServer config;
        #endregion
    }
}
